/*
 * dur_hmm.h
 *
 *  Created on: Sep 19, 2011
 *      Author: tqlong
 */

#ifndef DUR_HMM_H_
#define DUR_HMM_H_

#include <map>
#include "dhmm.h"

class DurationHMM : public DiscreteHMM
{
public:
  typedef std::vector<int> sequence_t;
  typedef std::map<int, double> duration_prob_t;
  typedef std::vector<duration_prob_t> dpvec_t;
  typedef DiscreteHMM::joint_seq_t joint_seq_t;
  typedef struct Variables {
    arma::mat alpha, beta;
    arma::mat alphaS, betaS;
    arma::vec ACC_start;
    arma::mat ACC_trans, ACC_emis;
    dpvec_t ACC_dprob;
  } variable_t;
  typedef std::vector<sequence_t> vseq_t;
  typedef duration_prob_t::value_type& pair_dprob_t;
  typedef const duration_prob_t::value_type& const_pair_dprob_t;
public:
  void load(const char* fileName);
  void save(const char* fileName);
  void rand();
  void generate(int T, joint_seq_t &seq);
  double seq_probability(const sequence_t& o);
  double seq_probability_reverse(const sequence_t& o);
  void map(joint_seq_t& seq);

  void set_prefix(const std::string& prefix) { prefix_ = prefix; }
  void train(const vseq_t& data, int max_iter = 10);
  double diff(DurationHMM& hmm);

  void print_params() const;
public:
  dpvec_t dprob_;
  variable_t var_;
  std::string prefix_;
protected:
  int duration_sample(const duration_prob_t& dp) const;
  void compute_alpha(const sequence_t& o, variable_t& var);
  void compute_beta(const sequence_t& o, variable_t& var);
  void compute_alphaS(const sequence_t& o, variable_t& var);
  void compute_betaS(const sequence_t& o, variable_t& var);

  double subseq_prob(const sequence_t& o, int start, int len, int state);
  void accumulate(const sequence_t& o, double weight);
  void reestimate();
};

#endif /* DUR_HMM_H_ */
